﻿using System;
using System.Collections.Generic;

namespace Chess.Common.Game
{
    public class Coordinate
    {
        public static readonly List<char> Files = new List<char> { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
        public static readonly List<char> Ranks = new List<char> { '1', '2', '3', '4', '5', '6', '7', '8' };

        public char File { get; private set; }
        public char Rank { get; private set; }

        public Coordinate(char file, char rank)
        {
            if (file < 'A' || file > 'H')
            {
                throw new ArgumentException("Invalid file: must be A..H");
            }
            if (rank < '1' || rank > '8')
            {
                throw new ArgumentException("Invalid rank: must be 1..8");
            }

            File = file;
            Rank = rank;
        }

        public Coordinate(string fileAndRank) :
            this(fileAndRank.ToUpper()[0], fileAndRank[1])
        {
            if (fileAndRank.Length != 2)
            {
                throw new ArgumentException("Invalid file and rank: must be of length 2");
            }
        }

        // these can be dangerous: do not over use!
        public static implicit operator Coordinate(string coordinate)
        {
            return new Coordinate(coordinate);
        }

        public Tuple<int, int> ToIndices()
        {
            return new Tuple<int, int>(File - 'A', Rank - '1');
        }

        public bool Equals(Coordinate other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return other.File == File && other.Rank == Rank;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof(Coordinate)) return false;
            return Equals((Coordinate)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (File.GetHashCode() * 397) ^ Rank.GetHashCode();
            }
        }
    }
}
